package com.sailors.common.task.provider.application.aggregation.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sailors.common.task.provider.application.aggregation.IFileTaskAggregation;
import com.sailors.common.task.provider.application.convert.FileTaskAggConver;
import com.sailors.common.task.provider.domian.service.IFileTaskService;
import com.sailors.common.task.provider.faced.model.dto.execute.FileTaskCreateExecuteDto;
import com.sailors.common.task.provider.faced.model.dto.execute.FileTaskFailedExecuteDto;
import com.sailors.common.task.provider.faced.model.dto.execute.RefreshProcessExecuteDto;
import com.sailors.common.task.provider.faced.model.dto.query.WebFileTaskQueryDto;
import com.sailors.common.task.provider.faced.model.vo.FileTaskLogDetailVo;
import com.sailors.common.task.provider.infra.remote.FileUploadRemoteService;
import com.sailors.common.task.provider.infra.repository.IFileTaskLogRepository;
import com.sailors.common.task.provider.infra.repository.model.FileTaskLogPo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * File task aggregation
 *
 * @description:
 * @author: cyj
 * @date 2023 -02-22 00:18:35
 */
@Service
public class FileTaskAggregation implements IFileTaskAggregation {

    @Autowired
    private IFileTaskLogRepository fileTaskLogRepository;

    @Autowired
    private IFileTaskService fileTaskService;

    @Autowired
    private FileUploadRemoteService fileUploadRemoteService;

    private final ExecutorService uploadCacheService = Executors.newCachedThreadPool();

    @Override
    public Page<FileTaskLogDetailVo> page(WebFileTaskQueryDto webFileTaskQueryDto) {

        Page<FileTaskLogPo> fileTaskLogPoPage = fileTaskLogRepository.commonPage(webFileTaskQueryDto);
        return FileTaskAggConver.INSTANCE.fileTaskLogPoPage2Vo(fileTaskLogPoPage);
    }

    @Override
    public FileTaskLogDetailVo get(Long id) {
        Page<FileTaskLogDetailVo> page = this.page(new WebFileTaskQueryDto(Arrays.asList(id)));
        return CollectionUtils.isNotEmpty(page.getRecords()) ? page.getRecords().get(0) : null;
    }

    @Override
    public List<FileTaskLogDetailVo> nowProcess(List<Long> ids) {
        Page<FileTaskLogDetailVo> page = this.page(new WebFileTaskQueryDto(ids));
        return page.getRecords();
    }

    @Override
    public List<String> bussiness() {
        return fileTaskLogRepository.bussiness();
    }

    @Override
    public Long create(FileTaskCreateExecuteDto fileTaskCreateExecuteDto) throws ExecutionException, InterruptedException {

        CompletableFuture task1 = CompletableFuture.supplyAsync(() -> {
            Optional.ofNullable(fileUploadRemoteService.uploadExcel(fileTaskCreateExecuteDto.getSourceExcel())).ifPresent(
                    fileTaskCreateExecuteDto::setSourceFileUrl
            );
            return null;
        }, uploadCacheService);

        CompletableFuture task2 = CompletableFuture.supplyAsync(() -> {
            Optional.ofNullable(fileUploadRemoteService.uploadExcel(fileTaskCreateExecuteDto.getReasonExcel())).ifPresent(
                    fileTaskCreateExecuteDto::setReasonUrl
            );
            return null;
        }, uploadCacheService);

        CompletableFuture.allOf(task1, task2).get();


        return fileTaskService.create(fileTaskCreateExecuteDto);
    }

    @Override
    public void refreshProcess(RefreshProcessExecuteDto refreshProcessExecuteDto) {

        Optional.ofNullable(fileUploadRemoteService.uploadExcel(refreshProcessExecuteDto.getSourceExcel())).ifPresent(
                refreshProcessExecuteDto::setSourceFileUrl
        );

        fileTaskService.refreshProcess(refreshProcessExecuteDto);
    }

    @Override
    public void failed(FileTaskFailedExecuteDto fileTaskFailedExecuteDto) throws ExecutionException, InterruptedException {

        CompletableFuture task1 = CompletableFuture.supplyAsync(() -> {
            Optional.ofNullable(fileUploadRemoteService.uploadExcel(fileTaskFailedExecuteDto.getReasonExcel())).ifPresent(
                    fileTaskFailedExecuteDto::setReasonUrl
            );
            return null;
        }, uploadCacheService);

        CompletableFuture task2 = CompletableFuture.supplyAsync(() -> {
            Optional.ofNullable(fileUploadRemoteService.uploadExcel(fileTaskFailedExecuteDto.getSuccessExcel())).ifPresent(
                    fileTaskFailedExecuteDto::setSuccessFileUrl
            );
            return null;
        }, uploadCacheService);

        CompletableFuture.allOf(task1, task2).get();

        fileTaskService.failed(fileTaskFailedExecuteDto);
    }
}
